Conversation
…injection, fix parseYamlSafe consistency Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-editor/sessions/fdecd5e6-5e99-4497-be49-ba1ed4033a96 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
…default key ordering, simplified passthrough extraction Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-editor/sessions/fdecd5e6-5e99-4497-be49-ba1ed4033a96 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
…se clearer destructuring names Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-editor/sessions/fdecd5e6-5e99-4497-be49-ba1ed4033a96 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves YAML round-tripping fidelity for workflow configs by preserving unknown top-level keys and restoring original top-level key ordering across parse → edit → export, while also fixing parseYamlSafe field loss and preventing unintended empty-section injection.
Changes:
- Add
_extraTopLevelKeystoWorkflowConfigand propagate it through parsing, node export, and YAML serialization. - Update
configToYamlto honor_originalKeysordering (with a default fallback order) and to emit preserved unknown keys. - Extend store import/export to persist non-visual metadata (
importedPassthrough) so export can reconstruct a complete config consistently.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/utils/serialization.ts | Preserve unknown top-level YAML keys, keep original top-level key order in configToYaml, and align parseYamlSafe field passthrough with parseYaml. |
| src/utils/serialization-bugs.test.ts | Add regression tests for unknown-key preservation, triggers injection avoidance, and parseYamlSafe field consistency. |
| src/types/workflow.ts | Extend WorkflowConfig with _extraTopLevelKeys for unknown top-level YAML preservation. |
| src/stores/workflowStore.ts | Persist imported non-visual metadata and pass it back into nodesToConfig to prevent metadata loss during export. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Preserve top-level key ordering and unknown keys from the main file | ||
| config._originalKeys = Object.keys(parsed); | ||
| const extraTopLevelKeys = extractExtraTopLevelKeys(parsed); | ||
| if (extraTopLevelKeys) { | ||
| config._extraTopLevelKeys = extraTopLevelKeys; | ||
| } |
There was a problem hiding this comment.
resolveImports() now captures _originalKeys and _extraTopLevelKeys from the main file, but the multi-file export path (exportToFiles/exportMainFileYaml via buildMainFileContent) does not use configToYaml and currently does not emit unknown top-level keys or preserve the original top-level key ordering. As a result, multi-file round-trips will still drop custom blocks (e.g. engine:) and reorder keys in the main file. Consider updating buildMainFileContent to incorporate _extraTopLevelKeys and honor _originalKeys (or delegate to configToYaml for the main-file content).
| const { nodes, edges, importedWorkflows, importedTriggers, importedPipelines, importedPassthrough } = get(); | ||
| const moduleTypeMap = useModuleSchemaStore.getState().moduleTypeMap; | ||
| const config = nodesToConfig(nodes, edges, moduleTypeMap); | ||
| // Pass importedPassthrough as originalConfig so that nodesToConfig can restore | ||
| // non-visual fields: name, version, _originalKeys, _extraTopLevelKeys, imports, | ||
| // requires, platform, infrastructure, sidecars. | ||
| const originalConfig: import('../types/workflow.ts').WorkflowConfig | undefined = importedPassthrough | ||
| ? { modules: [], workflows: {}, triggers: {}, ...importedPassthrough } | ||
| : undefined; | ||
| const config = nodesToConfig(nodes, edges, moduleTypeMap, originalConfig); |
There was a problem hiding this comment.
exportToConfig() always reuses importedPassthrough when present, but clearCanvas() does not reset importedPassthrough. This can cause stale name/version/_originalKeys/_extraTopLevelKeys/etc. from a previously imported YAML to leak into subsequent exports after clearing the canvas. Clear importedPassthrough (and potentially sourceMap) in clearCanvas(), or gate passthrough usage on whether a config was actually imported for the current session.
|
@copilot apply changes based on the comments in this thread |
…pipelines from passthrough type, fix buildMainFileContent for multi-file key ordering and unknown keys Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-editor/sessions/cbe50c21-b5cc-4238-ab7b-36cb53bc6e40 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-editor/sessions/cbe50c21-b5cc-4238-ab7b-36cb53bc6e40 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
… buildMainFileContent Agent-Logs-Url: https://github.com/GoCodeAlone/workflow-editor/sessions/cbe50c21-b5cc-4238-ab7b-36cb53bc6e40 Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Applied all three changes from the review thread (commit
|
Opening a workflow YAML file caused silent destructive changes: unknown top-level keys (e.g.
engine:) were deleted,triggers: {}was injected, top-level key ordering was scrambled, andparseYamlSafesilently droppedimports/requires/platform/infrastructure/sidecars.Root causes
parseYaml/parseYamlSafeonly handled known fields — anything else was discardedexportToConfig()callednodesToConfig()withoutoriginalConfig, bypassing the "omit if not originally present" guard fortriggers/workflows/modulesconfigToYamlused a hardcoded key order, ignoring the original file orderingparseYamlSafewas inconsistent withparseYaml(missing 5 passthrough fields)importFromConfigstored onlyimportedWorkflows/Triggers/Pipelines, losing all other original metadatabuildMainFileContent(multi-file export path) built output manually, bypassing_extraTopLevelKeysemission and_originalKeysorderingclearCanvas()did not resetimportedPassthrough, allowing stale metadata to leak into subsequent exportsChanges
src/types/workflow.ts_extraTopLevelKeys?: Record<string, unknown>toWorkflowConfigto carry unrecognised top-level keys through the full parse → store → serialize cyclesrc/utils/serialization.tsKNOWN_TOP_LEVEL_KEYSset (includingapplicationfor the legacy multi-file format) andextractExtraTopLevelKeys()helperparseYaml+parseYamlSafe: capture unknown top-level keys into_extraTopLevelKeysparseYamlSafe: fixed to matchparseYamlforimports,requires,platform,infrastructure,sidecarsnodesToConfig: pass through_extraTopLevelKeysfromoriginalConfigconfigToYaml: emit_extraTopLevelKeys; honour_originalKeysordering when serialising (falls back to documented fixed order when_originalKeysabsent)resolveImports: propagate_originalKeysand_extraTopLevelKeysfrom the main filebuildMainFileContent: now delegates toconfigToYamlso multi-file main-file exports also honour_originalKeysordering and emit_extraTopLevelKeys; ensuresmodulesis always present in the output for multi-file main files (even when all modules live in sub-files)src/stores/workflowStore.tsimportedPassthroughfield (type excludespipelines, which is tracked separately viaimportedPipelines) storing all non-visual config metadata (name,version,_originalKeys,_extraTopLevelKeys,imports,requires,platform,infrastructure,sidecars)importFromConfig: populatesimportedPassthroughvia destructuringexportToConfig: passesimportedPassthroughasoriginalConfigtonodesToConfig, restoring correct_originalKeysso the empty-section omission logic fires correctly and unknown keys are re-emittedclearCanvas: now resetsimportedPassthroughtonullto prevent stale metadata from a previous import leaking into subsequent exportsExample — before/after
Input YAML:
Before:
engine:block deleted,triggers: {}injected, key order changed.After:
engine:preserved,triggersabsent,name → engine → modules → pipelinesorder maintained. This fidelity now also applies to multi-file configs exported viabuildMainFileContent.